8.4.3 简单的curl

在Linux和MacOS(曾用名Mac OS X)系统里可以找到一个名为 curl 的命令行工具。这个工具可以对指定的URL发起HTTP请求,并保存返回的内容。通过使用 httpioos 包,我们可以用很少的几行代码来实现一个自己的 curl 工具。

让我们来看一下实现了基础 curl 功能的例子,如代码清单8-46所示。

代码清单8-46 listing46.go

01 // 这个示例程序展示如何使用io.Reader和io.Writer接口
02 // 写一个简单版本的curl
03 package main
04
05 import (
06   "io"
07   "log"
08   "net/http"
09   "os"
10 )
11
12 // main是应用程序的入口
13 func main() {
14   // 这里的r是一个响应,r.Body是io.Reader
15   r, err := http.Get(os.Args[1])
16   if err != nil {
17     log.Fatalln(err)
18   }
19
20   // 创建文件来保存响应内容
21   file, err := os.Create(os.Args[2])
22   if err != nil {
23     log.Fatalln(err)
24   }
25   defer file.Close()
26
27   // 使用MultiWriter,这样就可以同时向文件和标准输出设备
28   // 进行写操作
29   dest := io.MultiWriter(os.Stdout, file)
30
31   // 读出响应的内容,并写到两个目的地
32   io.Copy(dest, r.Body)
33   if err := r.Body.Close(); err != nil {
34     log.Println(err)
35   }
36 }

代码清单8-46展示了一个实现了基本骨架功能的 curl ,它可以下载、展示并保存任意的HTTP Get 请求的内容。这个例子会将响应的结果同时写入文件以及 stdout 。为了让例子保持简单,这个程序没有检查命令行输入参数的有效性,也没有支持更高级的选项。

在这个程序的第15行,使用来自命令行的第一个参数来执行HTTP Get 请求。如果这个参数是一个URL,而且请求没有发生错误,变量 r 里就包含了该请求的响应结果。在第21行,我们使用命令行的第二个参数打开了一个文件。如果这个文件打开成功,那么在第25行会使用 defer 语句安排在函数退出时执行文件的关闭操作。

因为我们希望同时向 stdout 和指定的文件里写请求的内容,所以在第29行我们使用 io 包里的 MultiWriter 函数将文件和 stdout 整合为一个 io.Writer 值。在第33行,我们使用 io 包的 Copy 函数从响应的结果里读取内容,并写入两个目的地。由于有 MultiWriter 函数提供的值的支持,我们可使用一次 Copy 调用,将内容同时写到两个目的地。

利用 io 包里已经提供的支持,以及 httpos 包里已经实现了 io.Writerio.Reader 接口类型的实现,我们不需要编写任何代码来完成这些底层的函数,借助已经存在的功能,将注意力集中在需要解决的问题上。如果我们自己的类型也实现了这些接口,就可以立刻支持已有的大量功能。

results matching ""

    No results matching ""